/**
 * @description 手写Promise
 * @author Randomize
 */

class MyPromise {
  state = 'pending'  // Promise初始化时状态
  value = undefined  // 成功后的值
  reason = undefined  // 失败后的原因
  resolveCallbacks = []  // pending状态下，存储成功的回调
  rejectCallbacks = []  // pending状态下，存储失败的回调

  constructor (fn) {
    // 期约履行后的回调
    const resolveHandler = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled'
        this.value = value
        this.resolveCallbacks.forEach(fn => fn(this.value))
      }
    }

    // 期约拒绝后的回调
    const rejectHandler = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected'
        this.reason = reason
        this.resolveCallbacks.forEach(fn => fn(this.reason))
      }
    }

    try {
      // 执行函数
      fn(resolveHandler, rejectHandler)
    } catch (error) {
      // 捕获错误
      rejectHandler(error)
    }
  }

  // then方法(第二个reject回调默认可以不传)
  then (fn1, fn2) {
    // 期约处于pending状态下，fn1，fn2会被存储到callbacks中
    // 判断传入的参数是否为函数，避免传入其他参数造成异常
    fn1 = typeof fn1 === 'function' ? fn1 : val => val
    fn2 = typeof fn2 === 'function' ? fn2 : err => err

    // 期约待定
    if (this.state === 'pending') {
      return new MyPromise((resolve, reject) => {
        this.resolveCallbacks.push(() => {
          try {
            const newValue = fn1(this.value)
            resolve(newValue)
          } catch (error) {
            reject(err)
          }
        })
        this.rejectCallbacks.push(() => {
          try {
            const newReason = fn2(this.reason)
            reject(newReason)
          } catch (error) {
            reject(error)
          }
        })
      })
    }
    // 期约履行
    if (this.state === 'fulfilled') {
      return new MyPromise((resolve, reject) => {
        try {
          const newValue = fn1(this.value)
          resolve(newValue)
        } catch (error) {
          reject(error)
        }
      })
    }
    // 期约拒绝
    if (this.state === 'rejected') {
      return new MyPromise((resolve, reject) => {
        try {
          const newReason = fn2(this.reason)
        } catch (error) {
          reject(error)
        }
      })
    }
  }

  catch (fn) {  // catch是then的语法糖
    return this.then(null, fn)
  }
}

// promise.resolve
MyPromise.resolve = function (value) {
  return new MyPromise((resolve, reject) => resolve(value))
}
// promise.reject
MyPromise.reject = function (reason) {
  return new MyPromise((resolve, reject) => reject(reason))
}
// promise.all
MyPromise.all = function (promiseList = []) {
  return new MyPromise((resolve, reject) => {
    const result = []  // 存储promiseList所有的结果
    const length = promiseList.length
    let resolvedCount = 0

    promiseList.forEach(p => {
      p.then(data => {
        result.push(data)

        // 注意，resolvedCount必须在then里做++运算，保证异步循环
        resolvedCount++
        if (resolvedCount === length) {
          // 已经遍历到最后一个promise
          resolve(result)
        }
      }).catch(err => {
        reject(err)  //如果有一个错误，则返回rejected
      })
    })
  })
}
// promise.race
MyPromise.race = function (promiseList = []) {
  let resolved = false // 标记
  return new MyPromise((resolve, reject) => {
    promiseList.forEach(p => {
      p.then(data => {
        if (!resolved) {
          resolve(data)
          resolved = true
        }
      }).catch((err) => {
        reject(err)
      })
    })
  })
}

// 测试代码
let p = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    // debugger
    resolve(100)
  }, 1000)
})

const p11 = p.then(data1 => {
  console.log('data1', data1)
  return data1 + 1
})

const p12 = p11.then(data2 => {
  console.log('data2', data2)
  return data2 + 2
})

// console.log(p)
const p2 = MyPromise.resolve('233')

console.log(MyPromise.resolve('100'))
console.log(MyPromise.all([p, p11, p12]))
const res = MyPromise.race([p, p11, p12, p2])
console.log(res)
